package com.hzit.payweb.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.hzit.paycommon.paycommonapi.enums.StatusEnum;
import com.hzit.paycommon.paycommonapi.resp.PayNotifyData;
import com.hzit.paycommon.paycommonapi.utils.PayDigestUtil;
import com.hzit.payweb.config.MqData;
import com.hzit.payweb.config.MyMessagePostProcessor;
import com.hzit.payweb.config.PayWebConfig;
import com.hzit.payweb.config.RabbitMqConfig;
import com.hzit.payweb.model.PaySerial;
import com.hzit.payweb.service.IPayNotifyService;
import com.hzit.payweb.service.IPaySerialService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;

/**
 * 支付宝异步通知
 */
@Service
public class PayNotifyServiceImpl implements IPayNotifyService {

    @Autowired
    private IPaySerialService iPaySerialService;

    private Logger logger = LoggerFactory.getLogger(PayNotifyServiceImpl.class);

    @Autowired
    private PayWebConfig payWebConfig;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 根据支付宝异步通知的参数去修改流水状态
     * @param paramsMap
     * @return
     */
    @Override
    public String updateSerial(HashMap<String, String> paramsMap) {

        //1.获取支付宝返回的参数
        String outTradeNo = paramsMap.get("out_trade_no");
        String tradeNo = paramsMap.get("trade_no");
        String tradeStatus = paramsMap.get("trade_status");
        String totalAmount = paramsMap.get("total_amount"); //为空
        String appId = paramsMap.get("app_id");
        String gmtPayment = paramsMap.get("gmt_payment"); //交易成功时间

        //2.商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号；
        PaySerial paySerial = iPaySerialService.queryInfoByOutTradeNo(outTradeNo);
        if(ObjectUtils.isEmpty(paySerial)){
            logger.info("更新支付流水状态失败，原因：支付宝返回的商户流水号：{}不存在...",outTradeNo);
            return "fail";
        }

        //3.判断 total_amount 是否确实为该订单的实际金额（即商户订单创建时的金额）；
        if(!paySerial.getAmount().toString().equals(totalAmount)){
            logger.info("商户流水号：{}更新支付流水状态失败，原因：支付宝返回金额：" +
                    "{}和数据库金额：{}不匹配...",outTradeNo,totalAmount,paySerial.getAmount());
            return "fail";
        }

        //4.校验通知中的 seller_id（或者 seller_email) 是否为 out_trade_no 这笔单据的对应的操作方（有的时候，一个商户可能有多个 seller_id/seller_email）
        if(!payWebConfig.getAlipaySellerId().equals(paramsMap.get("seller_email"))){
            logger.info("商户流水号：{}更新支付流水状态失败，原因：sellerId不一致：",outTradeNo);
            return "fail";
        }

        //5.验证 app_id 是否为该商户本身
        if(!payWebConfig.getAlipayAppId().equals(appId)){
            logger.info("商户流水号：{}更新支付流水状态失败，原因：app_id不一致：",outTradeNo);
            return "fail";
        }

        //6.更新流水
        PaySerial paySerial1 = new PaySerial();
        paySerial1.setId(paySerial.getId());
        paySerial1.setRespSerialNo(tradeNo);
        paySerial1.setUpdateTime(new Date());
        if(!StringUtils.isEmpty(gmtPayment)){
            paySerial1.setFinishedTime(DateUtil.parse(gmtPayment,"yyyy-MM-dd HH:mm:ss"));
        }
        if("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){
            paySerial1.setStatus(String.valueOf(StatusEnum.SUCCESS.getCode()));
            paySerial1.setRespMsg(StatusEnum.SUCCESS.getDesc());

        }else{
            paySerial1.setStatus(String.valueOf(StatusEnum.FAIL.getCode()));
            paySerial1.setRespMsg(StatusEnum.FAIL.getDesc());
        }
        iPaySerialService.updatePaySerialStatus(paySerial1);

        //7.通知业务系统更新。订单

        //通知参数：两个流水号，金额，状态，时间，支付方式，签名

        PayNotifyData payNotifyData = new PayNotifyData();
        payNotifyData.setAmount(paySerial.getAmount().toString());
        payNotifyData.setFinishedTime(gmtPayment);
        payNotifyData.setStatus(paySerial1.getStatus());
        payNotifyData.setDesc(paySerial1.getRespMsg());
        payNotifyData.setMchOrderNo(paySerial.getMchOrderNo());
        payNotifyData.setPaySerialNo(outTradeNo);
        payNotifyData.setPayWay("alipay"); //TODO

        //TODO

        JSONObject params = (JSONObject) JSONObject.toJSON(payNotifyData);
        String sign = PayDigestUtil.getSign(params, "test12345");
        params.put("sign",sign);
        //restTemplate发送http post请求
        String rlt = restTemplate.postForObject(payWebConfig.getOrderNotifyUrl(),payNotifyData,String.class);

        logger.info("----------------rlt = "+ rlt);
        //5分钟后执行
        if("success".equals(rlt)){
            //TODO 更新，通知结果表为成功
            return "success";
        }

        //5,5 1h.2h
        //继续通知，隔断时间 使用mq延时队列
        //继续放入队列，5
//        MyMessagePostProcessor myMessagePostProcessor = new MyMessagePostProcessor(3000);

        MqData mqData1 = new MqData();
        mqData1.setId(String.valueOf(System.currentTimeMillis()));
        mqData1.setPayNotifyData(payNotifyData);
        rabbitTemplate.convertAndSend(RabbitMqConfig.BUSINESS_EXCHANGE_NAME,"",mqData1);
        return "success";

    }
}
